package com.logicbus.backend.websocket;

import com.alogic.load.Loadable;
import com.alogic.xscript.Logiclet;
import com.alogic.xscript.Script;
import com.anysoft.util.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;

import javax.websocket.server.ServerEndpoint;
import java.util.Map;

/**
 * Endpoint信息封装
 *
 * @since 1.6.14.1 [20210310 duanyy] <br>
 */
public class WSEndpointInfo extends Loadable.Abstract implements XMLConfigurable, Configurable {

    /**
     * a logger of slf4j
     */
    protected static final Logger LOG = LoggerFactory.getLogger(WSEndpointInfo.class);
    protected String path = "";
    protected Class<?> clazz;
    protected Logiclet onOpen;
    protected Logiclet onClose;
    protected Logiclet onText;
    protected Logiclet onData;
    protected Logiclet onError;

    public Logiclet getOnOpen(){
        return onOpen;
    }

    public Logiclet getOnClose(){
        return onClose;
    }

    public Logiclet getOnData(){
        return onData;
    }

    public Logiclet getOnText(){
        return onText;
    }

    public Logiclet getOnError(){
        return onError;
    }

    public boolean isOk(){
        return clazz != null;
    }

    @Override
    public String getId() {
        return String.format("%s{path='%s'}",clazz.getName(),path);
    }

    public String getPath(){
        return path;
    }

    public Class<?> getClazz(){
        return clazz;
    }

    public WSEndpointInfo(){

    }

    public WSEndpointInfo(Class<?> clazz,String path){
        this.clazz = clazz;
        this.path = path;
    }

    public WSEndpointInfo(Class<?> clazz){
        this.clazz = clazz;
    }

    @Override
    public void report(Element xml) {
        if (xml != null){
            XmlTools.setString(xml,"class",clazz.getName());
            XmlTools.setString(xml,"path",path);
        }
    }

    @Override
    public void report(Map<String, Object> json) {
        if (json != null){
            JsonTools.setString(json,"class",clazz.getName());
            JsonTools.setString(json,"path",path);
        }
    }

    @Override
    public void configure(Properties p) {
        path = PropertiesConstants.getString(p,"path","",true);
        clazz = loadClass(PropertiesConstants.getString(p,"class","",true));
        if (StringUtils.isEmpty(path)){
            ServerEndpoint anno = (ServerEndpoint)clazz.getAnnotation(ServerEndpoint.class);
            if (anno != null) {
                path = anno.value();
            }
        }
    }

    private Class<?> loadClass(String aClass) {
        Class<?> found = null;
        if (StringUtils.isNotEmpty(aClass)){
            ClassLoader cl = Settings.getClassLoader();
            try {
                found = cl.loadClass(aClass);
            }catch (Exception ex){
                LOG.error("Can not load class:" + aClass);
            }
        }
        return found;
    }

    @Override
    public void configure(Element e, Properties p) {
        XmlElementProperties props = new XmlElementProperties(e,p);
        configure(props);

        onOpen = Script.createLogiclet(e,"on-open",props,null);
        onClose = Script.createLogiclet(e,"on-close",props,null);
        onError = Script.createLogiclet(e,"on-error",props,null);
        onData = Script.createLogiclet(e,"on-data",props,null);
        onText = Script.createLogiclet(e,"on-text",props,null);
    }

}
